package com.mf.generator.service.analyze.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mf.generator.dao.analyzer.MysqlGeneratorDao;
import com.mf.generator.domain.analyzer.mysql.Column;
import com.mf.generator.domain.analyzer.mysql.ColumnGenerator;
import com.mf.generator.domain.analyzer.mysql.MysqlGenerator;
import com.mf.generator.domain.basic.mapping.DataTypeMapping;
import com.mf.generator.domain.basic.template.Template;
import com.mf.generator.service.analyze.MysqlGeneratorService;
import com.mf.generator.service.basic.DataTypeMappingService;
import com.mf.generator.service.basic.TemplateService;
import com.mf.generator.utils.FileZipUtils;
import com.mf.generator.utils.StringFormatUtils;
import com.mf.generator.utils.VelocityUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * MYSQL元数据生成代码Dao层实现类
 * User: zhaoming
 * Date: 13-9-16
 * Time: 下午11:46
 * To change this template use File | Settings | File Templates.
 */
@Service
public class MysqlGeneratorServiceImpl implements MysqlGeneratorService {

    public Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private MysqlGeneratorDao mysqlGeneratorDao;
    @Resource
    private TemplateService templateService;
    @Resource
    private DataTypeMappingService dataTypeMappingService;

    /**
     * 查询数据库列表
     * @return 数据库列表
     */
    public List<ColumnGenerator> selectDatabase(){
        return mysqlGeneratorDao.selectDatabase();
    }

    /**
     * 根据数据库名查询所有表
     * @param columnGenerator 字段信息实体类
     * @return 表列表
     */
    public List<ColumnGenerator> selectTableNames(ColumnGenerator columnGenerator){
        return mysqlGeneratorDao.selectTableNames(columnGenerator);
    }

    /**
     * 根据数据库名查询所有字段
     * @param columnGenerator 字段信息实体类
     * @return 字段列表
     */
    public List<ColumnGenerator> selectColumnNames(ColumnGenerator columnGenerator){
        return mysqlGeneratorDao.selectColumnNames(columnGenerator);
    }

    /**
     * 生成代码-压缩包下载
     */
    public ResponseEntity<byte[]> generatorDownLoad(MysqlGenerator mysqlGenerator,HttpHeaders headers){
        try {
            HashMap<String, Object> hashMap = this.getTemplateVariables(mysqlGenerator);

            String currentProjectPath =  this.getClass().getResource("/").toString().substring("file:/".length());
            String templatePath = currentProjectPath + "templet"+File.separator;

            //模板列表
            List<Template> templateList = templateService.selectAll();
            for(Template template : templateList){
                String importFilePath = currentProjectPath + "temp"+File.separator + hashMap.get("tableClassNameEN");
                importFilePath =importFilePath + File.separator + hashMap.get("packagePath").toString().replaceAll("\\.","/");
                importFilePath =importFilePath + File.separator + template.getFilePath().replaceAll("\\.","/");
                importFilePath =importFilePath + File.separator + hashMap.get("tableClassNameEN") + template.getFileName();
                if(template.getCode().equals("sqlMapperTemplet")){
                    importFilePath = currentProjectPath + "temp"+File.separator+hashMap.get("tableClassNameEN");
                    importFilePath = importFilePath + File.separator + hashMap.get("tableClassNameEN") + template.getFileName();
                }
                File file = new File(importFilePath);
                    if (!file.exists()) {
                    File filePath = new File(file.getParent());
                    filePath.mkdirs();
                }
                //解析并创建文件
                VelocityUtils.generatorCode(templatePath, template.getTemplateName(), hashMap, importFilePath);
            }

            //生成压缩包
            String folderSrcPath = currentProjectPath + "temp"+File.separator+hashMap.get("tableClassNameEN")+File.separator;
            String forderDesPath = currentProjectPath + "temp"+File.separator+hashMap.get("tableClassNameEN")+".zip";
            FileZipUtils.zip(folderSrcPath, forderDesPath, "");
            //下载文件
            File file = new File(forderDesPath);
            InputStream inputStream = new FileInputStream(file);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", new String((hashMap.get("tableClassNameEN")+".zip").getBytes("gbk"),"iso-8859-1"));

            return new ResponseEntity<byte[]>(IOUtils.toByteArray(inputStream), headers, HttpStatus.CREATED);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 获取模板变量
     * @param mysqlGenerator
     * @return
     */
    private HashMap<String, Object> getTemplateVariables(MysqlGenerator mysqlGenerator){

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        String tablePrefix = mysqlGenerator.getTablePrefix();
        if(StringUtils.isNotBlank(tablePrefix)){
            tablePrefix = tablePrefix + "_";
        }
        String tableNameEN = mysqlGenerator.getTableName().replaceAll(tablePrefix, "");

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("packagePath", mysqlGenerator.getPackagePath());            //包路径
        hashMap.put("tableNameCH", mysqlGenerator.getTableComment());           //中文表名
        hashMap.put("tableNameEN", tableNameEN);                                //英文表名
        hashMap.put("tablePrefix", tablePrefix);                                //表名前缀
        hashMap.put("author", mysqlGenerator.getAuthor());                      //创建者
        hashMap.put("dateTime", sdf.format(new Date()));                        //创建日期

        hashMap.put("tableClassNameEN", StringFormatUtils.humptoUpperCaseFirstOne(tableNameEN, "_"));
        hashMap.put("tablePropertyNameEN", StringFormatUtils.humpToLowerCaseFirstOne(tableNameEN, "_"));

        //数据类型映射
        HashMap<String, DataTypeMapping> dataTypeMappingHashMap = new HashMap<String, DataTypeMapping>();
        List<DataTypeMapping> dataTypeMappingList = dataTypeMappingService.selectAll();
        for(DataTypeMapping dataTypeMapping : dataTypeMappingList){
            dataTypeMappingHashMap.put(dataTypeMapping.getDatabaseType(), dataTypeMapping);
        }

        ObjectMapper mapper = new ObjectMapper();
        List<ColumnGenerator> columnGeneratorList = new ArrayList<>();
        try {
            columnGeneratorList = mapper.readValue(mysqlGenerator.getColumnJson(), new TypeReference<List<ColumnGenerator>>() {});
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("JSON字符串转换实体对象失败", e);
        }


        //主键字段
        Column pkColumn = new Column();
        //扩展标识字段
        List<Column> extFlagColumns = new ArrayList<>();
        //逻辑标识字段
        Column effectiveFlagColumn = new Column();
        //普通字段
        List<Column> columns = new ArrayList<>();
        //模糊字段
        List<Column> likeColumns = new ArrayList<>();

        for(ColumnGenerator column : columnGeneratorList){
            DataTypeMapping dataTypeMapping = dataTypeMappingHashMap.get(column.getDataType());
            //判断是否为过滤字段
            if(StringUtils.isBlank(column.getFilterFlag())) {
                if(StringUtils.isNotBlank(column.getEffectiveFlag())){
                    //逻辑标识字段
                    effectiveFlagColumn.setColumnNameCH(column.getColumnComment());
                    effectiveFlagColumn.setColumnNameEN(column.getColumnName());
                    effectiveFlagColumn.setColumnPropertyName(StringFormatUtils.humpToLowerCaseFirstOne(column.getColumnName(), "_"));
                    effectiveFlagColumn.setColumnMethodName(StringFormatUtils.humptoUpperCaseFirstOne(column.getColumnName(), "_"));
                    effectiveFlagColumn.setJdbcType(StringUtils.upperCase(dataTypeMapping.getJdbcType()));
                    effectiveFlagColumn.setJavaType(dataTypeMapping.getJavaType());
                }else if(StringUtils.isNotBlank(column.getExtFlag())){
                    //扩展字段
                    Column extColumn = new Column();
                    extColumn.setColumnNameCH(column.getColumnComment());
                    extColumn.setColumnNameEN(column.getColumnName());
                    extColumn.setColumnPropertyName(StringFormatUtils.humpToLowerCaseFirstOne(column.getColumnName(), "_"));
                    extColumn.setColumnMethodName(StringFormatUtils.humptoUpperCaseFirstOne(column.getColumnName(), "_"));
                    extColumn.setJdbcType(StringUtils.upperCase(dataTypeMapping.getJdbcType()));
                    extColumn.setJavaType(dataTypeMapping.getJavaType());
                    extColumn.setAutoFill(column.getAutoFill());
                    extFlagColumns.add(extColumn);
                }else if(StringUtils.isBlank(column.getColumnKey()) || !column.getColumnKey().equals("PRI")){
                    //普通字段
                    Column commonColumn = new Column();
                    commonColumn.setColumnNameCH(column.getColumnComment());
                    commonColumn.setColumnNameEN(column.getColumnName());
                    commonColumn.setColumnPropertyName(StringFormatUtils.humpToLowerCaseFirstOne(column.getColumnName(), "_"));
                    commonColumn.setColumnMethodName(StringFormatUtils.humptoUpperCaseFirstOne(column.getColumnName(), "_"));
                    commonColumn.setJdbcType(StringUtils.upperCase(dataTypeMapping.getJdbcType()));
                    commonColumn.setJavaType(dataTypeMapping.getJavaType());
                    commonColumn.setLikeFlag(StringUtils.isNotBlank(column.getLikeFlag()));
                    columns.add(commonColumn);
                }else{
                    //主键
                    pkColumn.setColumnNameCH(column.getColumnComment());
                    pkColumn.setColumnNameEN(column.getColumnName());
                    pkColumn.setColumnPropertyName(StringFormatUtils.humpToLowerCaseFirstOne(column.getColumnName(), "_"));
                    pkColumn.setColumnMethodName(StringFormatUtils.humptoUpperCaseFirstOne(column.getColumnName(), "_"));
                    pkColumn.setJdbcType(StringUtils.upperCase(dataTypeMapping.getJdbcType()));
                    pkColumn.setJavaType(dataTypeMapping.getJavaType());
                }
            }
        }

        hashMap.put("pkColumn",pkColumn);
        hashMap.put("extFlagColumns",extFlagColumns);
        hashMap.put("effectiveFlagColumn",effectiveFlagColumn);
        hashMap.put("columns",columns);
        hashMap.put("columns",columns);

        return hashMap;
    }


}
